<template>
  <div class="media-upload">
    <div class="media-list">
      <!-- 已上传的媒体文件 -->
      <div
        v-for="(item, index) in mediaList"
        :key="index"
        class="media-item"
      >
        <div class="media-wrapper">
          <!-- 图片预览 -->
          <el-image
            v-if="item.type === 'image'"
            :src="item.url"
            fit="cover"
            class="uploaded-media"
            @click="handlePreview(item)"
          >
            <div slot="error" class="media-slot">
              <i class="el-icon-picture-outline"></i>
            </div>
          </el-image>

          <!-- 视频预览 -->
          <div v-else-if="item.type === 'video'" class="video-preview" @click="handlePreview(item)">
            <video
              :src="item.url"
              class="uploaded-media"
              preload="metadata"
              muted
            ></video>
            <div class="video-play-icon">
              <i class="el-icon-video-play"></i>
            </div>
          </div>


          <!-- 操作按钮（hover显示） -->
          <div class="media-actions">
            <span class="media-actions-span">
              <i class="el-icon-zoom-in" @click="handlePreview(item)"></i>
              <i class="el-icon-delete" @click="removeMedia(index)"></i>
            </span>
          </div>
        </div>
      </div>

      <!-- 上传按钮 -->
      <div v-if="mediaList.length < limit" class="upload-item">
        <el-upload
          :action="uploadUrl"
          :headers="headers"
          :show-file-list="false"
          :on-success="handleUploadSuccess"
          :before-upload="handleBeforeUpload"
          :on-error="handleUploadError"
          :on-progress="handleUploadProgress"
          accept=".jpg,.jpeg,.png,.gif,.mp4,.avi,.mov,.wmv,.flv,.mkv,.webm"
          class="media-uploader"
          :disabled="uploading"
        >
          <!-- 上传按钮 -->
          <div v-if="!uploading" class="upload-placeholder">
            <i class="el-icon-plus"></i>
            <div class="upload-text">上传图片/视频</div>
          </div>

          <!-- 上传进度遮挡层 -->
          <div v-else class="upload-progress-overlay">
            <div class="upload-progress-content">
              <el-progress
                type="circle"
                :percentage="uploadPercentage"
                :width="60"
                :show-text="false"
                :stroke-width="4"
                color="#409EFF"
              ></el-progress>
              <div class="progress-text">{{ uploadPercentage }}%</div>
              <div class="progress-status">{{ uploadStatus }}</div>
            </div>
            <!-- 遮挡背景 -->
            <div class="upload-mask"></div>
          </div>
        </el-upload>
      </div>
    </div>

    <!-- 上传提示 -->
    <div v-if="showTip" class="upload-tip">
      请上传
      <template v-if="fileSize">
        大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
      </template>
      格式为 <b style="color: #f56c6c">图片(JPG/PNG/GIF)或视频(MP4/AVI/MOV/WMV/FLV/MKV/WEBM)</b> 的文件
    </div>

    <!-- 预览对话框 -->
    <el-dialog
      :visible.sync="dialogVisible"
      :title="previewItem.type === 'video' ? '视频预览' : '图片预览'"
      width="800px"
      append-to-body
      @close="closePreview"
    >
      <!-- 图片预览 -->
      <img
        v-if="previewItem.type === 'image'"
        :src="previewItem.url"
        style="display: block; max-width: 100%; margin: 0 auto"
      />

      <!-- 视频预览 -->
      <video
        v-else-if="previewItem.type === 'video'"
        :src="previewItem.url"
        controls
        style="display: block; max-width: 100%; margin: 0 auto"
        preload="metadata"
      ></video>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from "@/utils/auth";
import { listByIds } from "@/api/system/oss";

export default {
  name: "MediaUpload",
  props: {
    value: {
      type: String,
      default: ""
    },
    // 文件数量限制
    limit: {
      type: Number,
      default: 5
    },
    // 大小限制(MB)
    fileSize: {
      type: Number,
      default: 100
    },
    // 是否显示提示
    isShowTip: {
      type: Boolean,
      default: true
    },
    // 是否返回URL而不是ossId
    returnUrl: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      mediaList: [],
      uploading: false,
      uploadPercentage: 0,
      uploadStatus: '准备上传',
      dialogVisible: false,
      previewItem: { type: '', url: '' },
      uploadUrl: process.env.VUE_APP_BASE_API + "/system/oss/upload",
      headers: {
        Authorization: "Bearer " + getToken()
      }
    };
  },
  computed: {
    showTip() {
      return this.isShowTip;
    }
  },
  watch: {
    value: {
      handler() {
        this.loadMedia();
      },
      immediate: true
    }
  },
  methods: {
    // 加载媒体数据
    async loadMedia() {
      if (!this.value) {
        this.mediaList = [];
        return;
      }

      try {
        const items = this.value.split(',').filter(item => item.trim());

        // 检查是否为URL格式
        const isUrl = items.some(item => item.startsWith('http'));

        if (isUrl) {
          // 如果是URL，直接构造媒体列表
          this.mediaList = items.map((url, index) => {
            const type = this.getMediaType(url);
            return {
              ossId: `temp_${index}`,
              url: url,
              name: `${type === 'video' ? '视频' : '图片'}_${index + 1}`,
              type: type
            };
          });
        } else {
          // 如果是ossId，调用接口获取详细信息
          const response = await listByIds(this.value);
          this.mediaList = response.data.map(item => ({
            ...item,
            type: this.getMediaType(item.url),
            name: item.fileName || item.originalName || '未命名文件'
          }));
        }
      } catch (error) {
        console.error('加载媒体数据失败:', error);
        this.mediaList = [];
      }
    },

    // 判断媒体类型
    getMediaType(url) {
      const videoExtensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv', '.webm'];
      const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'];

      const lowerUrl = url.toLowerCase();

      if (videoExtensions.some(ext => lowerUrl.includes(ext))) {
        return 'video';
      } else if (imageExtensions.some(ext => lowerUrl.includes(ext))) {
        return 'image';
      }

      // 默认返回图片类型
      return 'image';
    },

    // 上传前验证
    handleBeforeUpload(file) {
      // 文件类型验证
      const isValidType = this.validateFileType(file);
      if (!isValidType) {
        this.$modal.msgError('文件格式不正确，请上传图片(JPG/PNG/GIF)或视频(MP4/AVI/MOV/WMV/FLV/MKV/WEBM)格式文件!');
        return false;
      }

      // 文件大小验证
      const isValidSize = file.size / 1024 / 1024 < this.fileSize;
      if (!isValidSize) {
        this.$modal.msgError(`文件大小不能超过 ${this.fileSize}MB!`);
        return false;
      }

      // 开始上传
      this.uploading = true;
      this.uploadPercentage = 0;
      this.uploadStatus = '正在上传，请稍候...';

      // 显示全局loading（仿照ImageUpload）
      this.$modal.loading("正在上传文件，请稍候...");

      return true;
    },

    // 验证文件类型
    validateFileType(file) {
      const validTypes = [
        'image/jpeg', 'image/jpg', 'image/png', 'image/gif',
        'video/mp4', 'video/avi', 'video/quicktime', 'video/x-msvideo',
        'video/x-flv', 'video/x-matroska', 'video/webm'
      ];

      const validExtensions = [
        '.jpg', '.jpeg', '.png', '.gif',
        '.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv', '.webm'
      ];

      // 检查MIME类型
      if (validTypes.includes(file.type)) {
        return true;
      }

      // 检查文件扩展名
      const fileName = file.name.toLowerCase();
      return validExtensions.some(ext => fileName.endsWith(ext));
    },

    // 上传进度
    handleUploadProgress(event, file, fileList) {
      this.uploadPercentage = Math.round(event.percent);
      this.uploadStatus = `上传中... ${this.uploadPercentage}%`;
    },

    // 上传成功
    handleUploadSuccess(response, file, fileList) {
      this.uploading = false;
      this.uploadPercentage = 100;
      this.uploadStatus = '上传完成';

      // 关闭全局loading
      this.$modal.closeLoading();

      if (response.code === 200) {
        const mediaType = this.getMediaType(response.data.url);
        const newMedia = {
          ossId: response.data.ossId,
          url: response.data.url,
          name: response.data.fileName || response.data.originalName || '未命名文件',
          type: mediaType
        };

        this.mediaList.push(newMedia);
        this.emitChange();
        this.$modal.msgSuccess('上传成功!');
      } else {
        this.$modal.msgError(response.msg || '上传失败，请重试');
      }
    },

    // 上传失败
    handleUploadError(error, file, fileList) {
      this.uploading = false;
      this.uploadPercentage = 0;
      this.uploadStatus = '上传失败';

      // 关闭全局loading
      this.$modal.closeLoading();

      this.$modal.msgError('上传失败，请重试');
      console.error('上传错误:', error);
    },

    // 移除媒体
    removeMedia(index) {
      this.$confirm('确定要删除这个文件吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.mediaList.splice(index, 1);
        this.emitChange();
        this.$modal.msgSuccess('删除成功!');
      }).catch(() => {
        // 用户取消删除
      });
    },

    // 更新媒体名称
    updateMediaName(index, newName) {
      if (this.mediaList[index]) {
        this.mediaList[index].name = newName || '未命名文件';
        this.emitChange();
      }
    },

    // 预览媒体
    handlePreview(item) {
      this.previewItem = { ...item };
      this.dialogVisible = true;
    },

    // 关闭预览
    closePreview() {
      this.dialogVisible = false;
      this.previewItem = { type: '', url: '' };
    },

    // 发出变化事件
    emitChange() {
      const result = this.mediaList.map(item => {
        return this.returnUrl ? item.url : item.ossId;
      }).join(',');

      this.$emit('input', result);
      this.$emit('change', result);
    }
  }
};
</script>

<style scoped lang="scss">
.media-upload {
  .media-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }

  .media-item, .upload-item {
    width: 148px;
    height: 148px;
    position: relative;
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    overflow: hidden;

    &:hover {
      border-color: #409EFF;
    }
  }

  .media-wrapper {
    width: 100%;
    height: 100%;
    position: relative;

    .uploaded-media {
      width: 100%;
      height: 100%;
      object-fit: cover;
      cursor: pointer;
    }

    .video-preview {
      position: relative;
      width: 100%;
      height: 100%;
      cursor: pointer;

      .video-play-icon {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 24px;
        color: #fff;
        background: rgba(0, 0, 0, 0.5);
        border-radius: 50%;
        width: 40px;
        height: 40px;
        display: flex;
        align-items: center;
        justify-content: center;
        pointer-events: none;
      }
    }

    // hover显示的操作按钮
    .media-actions {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(0, 0, 0, 0.5);
      display: flex;
      align-items: center;
      justify-content: center;
      opacity: 0;
      transition: opacity 0.3s;

      .media-actions-span {
        display: flex;
        gap: 10px;

        i {
          color: #fff;
          font-size: 16px;
          cursor: pointer;
          padding: 5px;
          border-radius: 3px;

          &:hover {
            background: rgba(255, 255, 255, 0.2);
          }
        }
      }
    }

    &:hover {
      .media-actions {
        opacity: 1;
      }
    }
  }

  .upload-item {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fafafa;
    cursor: pointer;
    transition: all 0.3s;
    position: relative;

    &:hover {
      background: #f0f0f0;
    }

    .media-uploader {
      width: 100%;
      height: 100%;

      ::v-deep .el-upload {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }

    .upload-placeholder {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      color: #8c939d;

      i {
        font-size: 28px;
        margin-bottom: 8px;
      }

      .upload-text {
        font-size: 12px;
      }
    }

    // 上传进度遮挡层
    .upload-progress-overlay {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 10;

      .upload-progress-content {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        position: relative;
        z-index: 11;

        .progress-text {
          margin-top: 8px;
          font-size: 12px;
          color: #409EFF;
          font-weight: bold;
        }

        .progress-status {
          margin-top: 4px;
          font-size: 10px;
          color: #666;
        }
      }

      // 遮挡背景
      .upload-mask {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(255, 255, 255, 0.9);
        backdrop-filter: blur(2px);
        z-index: 10;
      }
    }
  }

  .upload-tip {
    margin-top: 8px;
    font-size: 12px;
    color: #666;
    line-height: 1.4;
  }

  .media-slot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background: #f5f7fa;
    color: #909399;
    font-size: 20px;
  }
}

// 去掉动画效果
::v-deep .el-list-enter-active,
::v-deep .el-list-leave-active {
  transition: all 0s;
}

::v-deep .el-list-enter,
::v-deep .el-list-leave-active {
  opacity: 0;
  transform: translateY(0);
}
</style>
